home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
LIB
/
UNIXLIB37B
/
!UnixLib37
/
src
/
unix
/
c
/
getcwd
< prev
next >
Wrap
Text File
|
1996-11-09
|
7KB
|
372 lines
/****************************************************************************
*
* $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/getcwd,v $
* $Date: 1996/10/30 21:59:01 $
* $Revision: 1.3 $
* $State: Rel $
* $Author: unixlib $
*
* $Log: getcwd,v $
* Revision 1.3 1996/10/30 21:59:01 unixlib
* Massive changes made by Nick Burret and Peter Burwood.
*
* Revision 1.2 1996/05/06 09:01:35 unixlib
* Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
* Saved for 3.7a release.
*
* Revision 1.1 1996/04/19 21:35:27 simon
* Initial revision
*
* Completely re-written by Alun Jones, auj@aber.ac.uk, 23/2/94,
* The original version corrupted the P.S.D. when run.
*
* OS_Args 7 and Prefix$Dir hacke by Simon Callan
* thanks to Andy (torq@gnu.ai.mit.edu) for the OS calls.
***************************************************************************/
static const char rcs_id[] = "$Id: getcwd,v 1.3 1996/10/30 21:59:01 unixlib Rel $";
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/os.h>
#include <sys/param.h>
#include <sys/syslib.h>
#include <sys/swis.h>
char *
getcwd (char *buffer, size_t size)
{
char ro_path[MAXPATHLEN];
char var[30]; /* Added by Steffan Corley,
is there a known limit on the length of this variable? */
char *rp = ro_path + MAXPATHLEN - 1;
char b[MAXPATHLEN];
register char *s, *t;
int r[10];
_kernel_oserror *e;
int handle;
if (size == 0 && buffer)
{
errno = EINVAL;
return 0;
}
/* Try to read CSD variable - added by Steffan Corley for !Virtual
compatibility */
r[0] = (int) "FileSwitch$CurrentFilingSystem";
r[1] = (int) ro_path;
r[2] = MAXPATHLEN - 1;
r[3] = 0;
r[4] = 0;
os_swi (OS_ReadVarVal, r);
if (r[2] > 0)
{
ro_path[r[2]] = '\0';
strcpy (var, "FileSwitch$");
strcat (var, ro_path);
strcat (var, "$CSD");
strcat (ro_path, ":");
r[0] = (int) var;
r[1] = (int) (ro_path + (handle = strlen (ro_path)));
r[2] = MAXPATHLEN - 1 - handle;
r[3] = 0;
r[4] = 0;
os_swi (OS_ReadVarVal, r);
if (r[2] > 0)
{ /* Read CSD var worked, parse the path name */
ro_path[r[2] + handle] = '\0';
s = ro_path;
t = buffer;
*t++ = '/';
size--;
while (*s && *s != '$' && size-- > 0)
*t++ = *s++;
while (*s && size-- > 0)
{
if (*s != '.')
*t++ = *s;
else
*t++ = '/';
s++;
}
if (size == 0)
{
errno = ERANGE;
return 0;
}
else
{
*t = '\0';
return buffer;
}
}
}
/* Try OS_Args 7 (get cannonicalised name) */
/* Open CSD for read only */
if (!os_fopen (0x40, "@", &handle))
{
r[0] = 7;
r[1] = handle;
r[2] = (int) ro_path;
r[5] = MAXPATHLEN;
e = os_swi (OS_Args, r);
os_fclose (handle);
if (!e)
{ /* OS_ARGS 7 worked, parse the path name */
s = ro_path;
t = buffer;
*t++ = '/';
size--;
while (*s && *s != '$' && size-- > 0)
*t++ = *s++;
while (*s && size-- > 0)
{
if (*s != '.')
*t++ = *s;
else
*t++ = '/';
s++;
}
if (size == 0)
{
errno = ERANGE;
return 0;
}
else
{
*t = '\0';
return buffer;
}
}
}
r[0] = (int) "Prefix$Dir";
r[1] = (int) ro_path;
r[2] = MAXPATHLEN - 1;
r[3] = 0;
r[4] = 0;
os_swi (OS_ReadVarVal, r);
if (r[2] > 0)
{
ro_path[r[2]] = '\0';
s = ro_path;
t = buffer;
*t++ = '/';
size--;
while (*s && *s != '$' && size-- > 0)
*t++ = *s++;
while (*s && size-- > 0)
{
if (*s != '.')
*t++ = *s;
else
*t++ = '/';
s++;
}
if (size == 0)
{
errno = ERANGE;
return 0;
}
else
{
*t = '\0';
return buffer;
}
}
/* Search backwards up the tree.
*/
*rp = 0;
while (1)
{
/* Read current directory name
*/
r[0] = 6;
r[2] = (int) b;
if (e = os_swi (OS_GBPB, r))
{
/* Failed to read dirname
* So swap CSD & PSD then chdir back to original
* directory.
*/
__seterr (e);
if (*rp)
{
r[0] = 0;
r[1] = (int) "\\";
if (!os_swi (OS_FSControl, r))
{
/* cd \ successful, so now need to cd \.{rp}
*/
*--rp = '.';
*--rp = '\\';
}
r[0] = 0;
r[1] = (int) rp;
os_swi (OS_FSControl, r);
}
return 0;
}
/* If at root directory then break
*/
if ((b[2] == '$') && (b[1] == 1))
{
break;
}
/* Copy the directory name into the RISC OS name
* buffer.
*/
rp -= b[1];
memcpy (rp, b + 2, b[1]);
*--rp = '.';
/* Now select PSD.
*/
r[0] = 0;
r[1] = (int) "\\";
if (os_swi (OS_FSControl, r))
{
/* If cd \ failed then just cd ^
*/
r[0] = 0;
r[1] = (int) "^";
os_swi (OS_FSControl, r);
}
else
{
/* Select new PSD.^
* This ensures that the PSD doesn't get corrupted by
* calling getcwd()
*/
r[0] = 0;
r[1] = (int) "\\.^";
os_swi (OS_FSControl, r);
}
}
/* OK, reached the root directory.
*/
*--rp = '$';
/* Again, PSD then original directory
*/
r[0] = 0;
r[1] = (int) "\\";
if (e = os_swi (OS_FSControl, r))
{
__seterr (e);
return 0;
}
r[0] = 0;
r[1] = (int) rp;
if (e = os_swi (OS_FSControl, r))
{
__seterr (e);
return 0;
}
/* OK, rp now contains the current directory, and
* the PSD is unchanged.
*
* Next find the FS name.
*/
/* FS number
*/
if (e = os_args (0, 0, 0, r))
{
__seterr (e);
return 0;
}
/* Convert number to name
*/
r[1] = r[0];
r[2] = (int) b + 1;
r[3] = MAXPATHLEN;
r[0] = 33;
if (e = os_swi (OS_FSControl, r))
{
__seterr (e);
return (0);
}
/* Now have "/ADFS::", for example in b.
*/
b[0] = '/';
strcat (b, "::");
/* Copy the disk name across to v
*/
if (strlen (b) < size)
{
strcpy (buffer, b);
}
else
{
errno = ERANGE;
return 0;
}
/* Next find the disk name
*/
r[0] = 5;
r[2] = (int) b;
if (e = os_swi (OS_GBPB, r))
{
__seterr (e);
return 0;
}
*(b + b[0] + 1) = '\0';
strcat (b, ".$");
if (strlen (buffer) + strlen (b + 1) < size)
{
strcat (buffer, b + 1);
}
else
{
errno = ERANGE;
return 0;
}
/* buffer now contains "/ADFS::fred.$", for example.
* Finally convert the RISC OS name from rp, appending it to v.
*/
s = buffer + strlen (buffer);
for (t = rp + 1; *t; t++)
{
if (s - buffer == size)
{
errno = ERANGE;
return 0;
}
*s++ = (*t == '.') ? '/' : *t;
}
*s = '\0';
return buffer;
}
/* BSD version of getcwd. */
char *
getwd (char *buffer)
{
return getcwd (buffer, 256);
}